package utils

import (
	"context"
	"errors"
	"fmt"
	"github.com/go-redis/redis/v8"
	"github.com/spf13/viper"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log"
	"os"
	"strconv"
	"time"
)

var (
	MysqlDB      *gorm.DB
	RedisDB      *redis.Client
	RedisContext = context.Background()
)

type configValues struct {
	key    []string
	values []string
}

func initConfig() {
	dir, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	viper.SetConfigType("json")
	viper.SetConfigName("config")
	viper.AddConfigPath(dir)
	err = viper.ReadInConfig()
	if err != nil {
		panic(errors.New("检查配置文件"))
	}
	logs := logger.New(log.New(os.Stdout, "\r\n", log.LstdFlags),
		logger.Config{
			SlowThreshold:             time.Second, //慢sql阀值
			LogLevel:                  logger.Info, //级别
			IgnoreRecordNotFoundError: true,
			Colorful:                  true, //彩色
		})
	err = initMysql(logs)
	if err != nil {
		panic("检查mysql是否开启")
	}
	err = initRedis()
	if err != nil {
		panic("检查redis服务是否开启")
	}
	defer func() {
		errs := recover()
		if errs != nil {
			panic(errs)
		}

	}()
}

func initRedis() error {
	redisConfig := readConfigValue("redis.ip", "redis.port", "redis.pwd", "redis.db").GetValue()
	rc := redisConfig.ValueToString()
	RedisDB = redis.NewClient(&redis.Options{
		Addr:     rc[0] + ":" + rc[1],
		Password: rc[2],
		DB:       redisConfig.ValueToInt(3),
	})
	_, err := RedisDB.Ping(RedisContext).Result()
	if err != nil {
		return err
	}
	return nil
}

func initMysql(l logger.Interface) (err error) {
	mysqlConfig := readConfigValue("mysql.username", "mysql.pwd", "mysql.ip", "mysql.port", "mysql.dbname", "mysql.charset").GetValue().ValueToString()
	dns := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local", listStringToAnyList(mysqlConfig)...)
	//log.Fatal(mysqlConfig)
	MysqlDB, err = gorm.Open(mysql.Open(dns),
		&gorm.Config{Logger: l},
	)
	return err
}
func readConfigValue(key ...string) *configValues {
	return &configValues{key: key, values: make([]string, len(key))}
}
func (c *configValues) GetValue() *configValues {
	if len(c.key) < 1 {
		return &configValues{values: nil}
	}
	if len(c.key) < 2 {
		return &configValues{values: []string{viper.GetString(c.key[0])}}
	}

	for i := 0; i < len(c.key); i++ {
		c.values[i] = viper.GetString(c.key[i])
	}
	//fmt.Printf("values= %v", c.key)
	return c
}
func (c *configValues) ValueToString() []string {
	return c.values
}
func (c *configValues) ValueToInt(i int) int {
	if i >= len(c.values) {
		return 0
	}
	atoi, err := strconv.Atoi(c.values[i])
	if err != nil {
		return 0
	}
	return atoi
}
func listStringToAnyList(s []string) (arr []any) {
	arr = make([]any, len(s))
	for i, v := range s {
		arr[i] = v
	}
	return
}

func init() {
	initConfig()
}
